package main

import (
    "bufio"
    "errors"
    "fmt"
    "os"
    "os/exec"
    "runtime"
)


var (
    dirSeparator string = "/"
    tempDir      string
)

func init() {
    if runtime.GOOS == "windows" {
        dirSeparator = "\\"
    }
    tempDir = os.TempDir() + dirSeparator + "goeval"
    os.Mkdir(tempDir, os.ModePerm)
}

func main() {
    result, err := eval(`println("hasaki")`)
    if err != nil {
        fmt.Println("error:", err)
    }
    fmt.Println(result)
}

// 写入一个文件然后用命令行来执行类似用了其他语言的子进程
func eval(code string, imports ...string) (result string, err error) {
    tmpfile, err := os.Create(tempDir + dirSeparator + "temp.go")
    if err != nil {
        return "", err
    }
    w := bufio.NewWriter(tmpfile)
    w.WriteString("package main\r\n")
    w.WriteString("\r\n")
    if len(imports) > 0 {
        tmpArgs := []string{"get"}
        tmpArgs = append(tmpArgs, imports...)
        goget := exec.Command("go", tmpArgs...)
        _, err = goget.Output()
        if err != nil {
            return "", err
        }
        w.WriteString("import (\r\n")
        for _, v := range imports {
            w.WriteString("\t" + `"` + v + `"` + "\r\n")
        }
        w.WriteString(")\r\n")
        w.WriteString("\r\n")
    }
    w.WriteString("func main() {\r\n")
    w.WriteString("\t" + code + "\r\n")
    w.WriteString("}\r\n")
    w.Flush()
    tmpfile.Close()
    cmd := exec.Command("go", "run", tmpfile.Name())
    res, err := cmd.CombinedOutput()
    if err != nil {
        return "", errors.New(string(res) + err.Error())
    }
    os.Remove(tmpfile.Name())
    return string(res), nil
}


// 结果 ： hasaki